﻿using JianZhangTool.config;
using JianZhangTool.menu;
using JianZhangTool.net;
using JianZhangTool.statistics;
using JianZhangTool.tool;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace JianZhangTool
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();
            Instance = this;
            StaticConfig.Load();
            Init();
            FormClosing += Main_FormClosing;
            // 判断自动连接
            if (auto_connect_checkbox.Checked && !bili_address_textbox.Text.Equals(""))
            {
                bili_connect_button_Click(null, null);
            }
        }

        public static Main Instance;

        /// <summary>
        /// BILIBILI获取真实房间ID
        /// </summary>
        private const string bili_api_roomid_url = "https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=";
        /// <summary>
        /// BILIBILI获取弹幕服务器信息
        /// </summary>
        private const string bili_api_danmu_server_url = "https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id={0}&type=0";


        /// HTTP客户端
        /// </summary>
        private HttpClient http_client;

        /// <summary>
        /// 是否连接了弹幕服务器
        /// </summary>
        private bool connected = false;
        /// <summary>
        /// 是否连接中
        /// </summary>
        private bool connecting = false;
        /// <summary>
        /// <summary>
        /// 直播信息
        /// </summary>
        private BiliLiveInfo liveInfo = new BiliLiveInfo();
        /// <summary>
        /// 弹幕服务器长连接
        /// </summary>
        // private BiliDanmuConnecterWS danmu_conn;
        private BiliDanmuConnecterTCP danmu_conn;

        /// <summary>
        /// 存储线程
        /// </summary>
        private Thread save_thread;

        /// <summary>
        /// 初始化信息
        /// </summary>
        private void Init()
        {
            if (StaticConfig.last_origin_roomId != 0)
            {
                bili_address_textbox.Text = StaticConfig.last_origin_roomId + "";
            }
            auto_connect_checkbox.Checked = StaticConfig.auto_connect != 0;

            save_thread = new Thread(() =>
            {
                RunSave();
            });
            save_thread.Start();
        }

        /// <summary>
        /// 循环存储
        /// </summary>
        private void RunSave()
        {
            while (true)
            {
                if (roomGuardInfos != null)
                {
                    roomGuardInfos.Save();
                }
                Thread.Sleep(5000);
            }
        }

        /// <summary>
        /// 提示框
        /// </summary>
        private FixedMessage message_box;

        /// <summary>
        /// 弹出提示窗
        /// </summary>
        /// <param name="title"></param>
        /// <param name="text"></param>
        public void show_message(string title, string text)
        {
            if (message_box == null)
            {
                message_box = new FixedMessage();
            }
            message_box.setMessage(title, text);
            int x = Left + (Width - message_box.Width) / 2;
            int y = Top + (Height - message_box.Height) / 2;
            message_box.Location = new System.Drawing.Point(x, y);

            message_box.ShowDialog();
        }

        /// <summary>
        /// 日志列表
        /// </summary>
        List<string> log_str_list = new List<string>();

        /// <summary>
        /// 添加日志
        /// </summary>
        /// <param name="log_str"></param>
        public void add_log(string log_str)
        {
            log_str_list.Add(log_str);
            if (log_str_list.Count > 50)
            {
                log_str_list.RemoveAt(0);
            }
            bili_log_textbox.Lines = log_str_list.ToArray();
            bili_log_textbox.SelectionStart = bili_log_textbox.Text.Length;
            bili_log_textbox.ScrollToCaret();
        }

        /// <summary>
        /// 点击连接弹幕服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void bili_connect_button_Click(object sender, EventArgs e)
        {
            if (connected)
            {
                show_message("错误", "请断开连接后再重连!");
                return;
            }
            // 首先获取弹幕服务器的连接信息
            string bili_address = bili_address_textbox.Text;
            int origin_roomId;
            try
            {
                origin_roomId = int.Parse(bili_address);
            }
            catch (Exception)
            {
                show_message("错误", "请输入正确的数字地址!");
                return;
            }
            add_log("[info] origin_roomId=" + origin_roomId + " 尝试获取弹幕服务器信息...");
            if (http_client == null)
            {
                http_client = new HttpClient()
                {
                    Timeout = TimeSpan.FromSeconds(5)
                };
            }
            // 记录原始房间ID
            liveInfo.origin_roomId = origin_roomId;
            if (await trigger_danmu_connect())
            {
                StaticConfig.last_origin_roomId = origin_roomId;
                StaticConfig.Save();
            }
        }

        /// <summary>
        /// 触发连接弹幕服务器
        /// </summary>
        /// <returns></returns>
        private async Task<bool> trigger_danmu_connect(bool reconnect = false)
        {
            if (connecting)
            {
                return false;
            }
            connecting = true;
            try
            {
                string ret;
                // 获取房间信息
                string room_url = bili_api_roomid_url + liveInfo.origin_roomId;
                try
                {
                    ret = await http_client.GetStringAsync(room_url);
                    // add_log(ret);
                }
                catch (Exception)
                {
                    show_message("错误", "网络连接失败!");
                    add_log("[error] origin_roomId=" + liveInfo.origin_roomId + " 获取房间信息 网络连接失败!");
                    return false;
                }
                JObject room_json = JObject.Parse(ret);
                if (room_json["code"].Value<int>() != 0)
                {
                    show_message("错误", "房间号不存在!");
                    add_log("[error] origin_roomId=" + liveInfo.origin_roomId + " 获取房间信息 房间号不存在!");
                    return false;
                }
                // 获取直播信息
                liveInfo.roomId = room_json["data"]["room_info"]["room_id"].Value<int>();
                liveInfo.title = room_json["data"]["room_info"]["title"].ToString();
                liveInfo.uname = room_json["data"]["anchor_info"]["base_info"]["uname"].ToString();

                // 获取弹幕服务器信息
                string danmu_url = string.Format(bili_api_danmu_server_url, liveInfo.roomId);
                try
                {
                    ret = await http_client.GetStringAsync(danmu_url);
                    // add_log(ret);
                }
                catch (Exception)
                {
                    show_message("错误", "网络连接失败!");
                    add_log("[error] origin_roomId=" + liveInfo.origin_roomId + " 获取弹幕服务器信息 网络连接失败!");
                    return false;
                }
                danmu_conn = new BiliDanmuConnecterTCP(liveInfo.roomId); 
                if (await danmu_conn.connect())
                {
                    connected = true;
                    if (!reconnect)
                    {
                        roomGuardInfos = new RoomGuardInfos(liveInfo.origin_roomId);
                    }
                    add_log("[info] roomId=" + liveInfo.roomId + " 弹幕服务器连接成功!");
                    bili_refresh_room_state();
                }
                else
                {
                    add_log("[info] roomId=" + liveInfo.roomId + " 弹幕服务器连接失败!");
                    await danmu_conn.disconnect();
                    connected = false;
                    if (roomGuardInfos != null)
                    {
                        roomGuardInfos.Save();
                        roomGuardInfos = null;
                    }
                    danmu_conn = null;
                    liveInfo.clear();
                    bili_refresh_room_state();
                }
                /*JObject danmu_json = JObject.Parse(ret);
                if (danmu_json["code"].Value<int>() != 0)
                {
                    show_message("错误", "弹幕服务器信息拉取失败!");
                    add_log("[error] origin_roomId=" + liveInfo.origin_roomId + " 获取弹幕服务器信息 弹幕服务器信息拉取失败!");
                    return false;
                }
                // 建立弹幕服务器长连接
                add_log("[info] roomId=" + liveInfo.roomId + " 尝试连接弹幕服务器...");
                string token = danmu_json["data"]["token"].ToString();
                danmu_conn = new BiliDanmuConnecterWS(liveInfo.roomId, token);
                if (await danmu_conn.connect())
                {
                    connected = true;
                    if (!reconnect)
                    {
                        roomGuardInfos = new RoomGuardInfos(liveInfo.origin_roomId);
                    }
                    add_log("[info] roomId=" + liveInfo.roomId + " 弹幕服务器连接成功!");
                    bili_refresh_room_state();
                }
                else
                {
                    add_log("[info] roomId=" + liveInfo.roomId + " 弹幕服务器连接失败!");
                    danmu_conn.disconnect();
                    connected = false;
                    if (roomGuardInfos != null)
                    {
                        roomGuardInfos.Save();
                        roomGuardInfos = null;
                    }
                    danmu_conn = null;
                    liveInfo.clear();
                    bili_refresh_room_state();
                }*/
                return true;
            }
            finally
            {
                connecting = false;
            }
        }

        /// <summary>
        /// 触发断开弹幕服务器
        /// </summary>
        public async Task trigger_danmu_disconnect(bool reconnect)
        {
            if (reconnect)
            {
                add_log("[info] roomId=" + liveInfo.roomId + " 弹幕服务器断开!");
                add_log("[info] roomId=" + liveInfo.roomId + " 弹幕服务器尝试重连...");
                await trigger_danmu_connect(true);
            }
            else
            {
                add_log("[info] roomId=" + liveInfo.roomId + " 弹幕服务器主动断开!");
                danmu_conn = null;
                connected = false;
                if (roomGuardInfos != null)
                {
                    roomGuardInfos.Save();
                    roomGuardInfos = null;
                }
                liveInfo.clear();
                bili_refresh_room_state();
            }
        }

        /// <summary>
        /// 刷新标签信息
        /// </summary>
        private void bili_refresh_room_state()
        {
            if (connected)
            {
                bili_conn_state_label.ForeColor = System.Drawing.Color.Green;
                bili_conn_state_label.Text = "[" + liveInfo.uname + "] " + liveInfo.title;
            }
            else
            {
                bili_conn_state_label.ForeColor = System.Drawing.Color.Gray;
                bili_conn_state_label.Text = "未连接";
                if (guard_statistics_form != null && guard_statistics_form.Visible)
                {
                    guard_statistics_form.Close();
                }
            }
            statistics_button.Enabled = connected;
        }

        /// <summary>
        /// 触发断开弹幕服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bili_disconnect_button_Click(object sender, EventArgs e)
        {
            if (!connected)
            {
                return;
            }
            if (danmu_conn != null)
            {
                _ = danmu_conn.disconnect();
            }
        }

        /// <summary>
        /// 点选自动连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void auto_connect_checkbox_CheckedChanged(object sender, EventArgs e)
        {
            if (auto_connect_checkbox.Checked)
            {
                StaticConfig.auto_connect = 1;
            }
            else
            {
                StaticConfig.auto_connect = 0;
            }
            StaticConfig.Save();
        }

        /// <summary>
        /// 房间舰长统计数据
        /// </summary>
        private RoomGuardInfos roomGuardInfos;

        /// <summary>
        /// 获取房间信息
        /// </summary>
        /// <returns></returns>
        public RoomGuardInfos GetRoomGuardInfos()
        {
            return roomGuardInfos;
        }

        /// <summary>
        /// 统计面板
        /// </summary>
        private GuardStatisticsForm guard_statistics_form;

        /// <summary>
        /// 点击弹出统计面板
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void statistics_button_Click(object sender, EventArgs e)
        {
            if (guard_statistics_form == null)
            {
                guard_statistics_form = new GuardStatisticsForm();

                int x = Left + (Width - guard_statistics_form.Width) / 2;
                int y = Top + (Height - guard_statistics_form.Height) / 2;
                guard_statistics_form.Location = new System.Drawing.Point(x, y);

                guard_statistics_form.ReloadCurrentRoomInfo();
                guard_statistics_form.Show();
            }
            else
            {
                if (guard_statistics_form.Visible)
                {
                    guard_statistics_form.Close();
                }
                else
                {
                    guard_statistics_form.Show();
                }
            }
        }

        /// <summary>
        /// 关于面板
        /// </summary>
        private About about_form;

        /// <summary>
        /// 点击弹出关于面板
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void main_menu_options_about_Click(object sender, EventArgs e)
        {
            if (about_form == null)
            {
                about_form = new About();
            }

            int x = Left + (Width - about_form.Width) / 2;
            int y = Top + (Height - about_form.Height) / 2;
            about_form.Location = new System.Drawing.Point(x, y);

            about_form.ShowDialog();
        }

        /// <summary>
        /// 点击关闭工具
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void main_menu_options_quit_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// 深渊参数面板
        /// </summary>
        private ShenyuanParams shenyuan_params_form;

        /// <summary>
        /// 点击弹出深渊配置面板
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void main_menu_params_guard_Click(object sender, EventArgs e)
        {
            if (shenyuan_params_form == null)
            {
                shenyuan_params_form = new ShenyuanParams();
            }

            int x = Left + (Width - shenyuan_params_form.Width) / 2;
            int y = Top + (Height - shenyuan_params_form.Height) / 2;
            shenyuan_params_form.Location = new System.Drawing.Point(x, y);

            shenyuan_params_form.ShowDialog();
        }

        /// <summary>
        /// 关闭时触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Main_FormClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // 存储
            if (roomGuardInfos != null)
            {
                roomGuardInfos.Save();
                roomGuardInfos = null;
            }
            // 由于统计面板不会自主释放 则在此处释放
            if (guard_statistics_form != null)
            {
                guard_statistics_form.Destroy();
            }
            // 强制退出存储线程
            if (save_thread != null)
            {
                save_thread.Abort();
            }
            Dispose();
        }
    }
}
